import threading
import queue
import time
from datetime import datetime

from xbase_util.common_util import date2s, s2date

from base.util.api_util import ApiUtil
from capture_api import configDao
from global_ver import flowDao


class TaskQueue:
    def __init__(self):
        self.scheduled_threads_info = None
        self.task_queue = queue.Queue()
        self.threads_info = []
        self.manager_thread = threading.Thread(target=self._process_queue)
        self.stop_event = threading.Event()
        self.manager_thread.start()
        print("初始化:任务管理器")

    def _process_queue(self):
        while not self.stop_event.is_set():
            if not self.task_queue.empty():
                thread = self.task_queue.get()
                for info in self.threads_info:
                    if info["thread"] == thread:
                        info["isRunning"] = True
                        info["isFinish"] = False
                        info["start_time"] = date2s(datetime.now())
                thread.start()
                thread.join()
                for info in self.threads_info:
                    if info["thread"] == thread:
                        info["isRunning"] = False
                        info["isFinish"] = True
                        info["end_time"] = date2s(datetime.now())

    def scheduled_thread_method(self, bean, flow, config, request):
        start_time = bean.scheduled_start_time
        while True:
            if self.scheduled_threads_info['scheduled_block_running']:
                break
            start_time = s2date(start_time)
            end_time = start_time + bean.scheduled_period_minutes
            print("要保证当前时间>要获取的结束时间")
            while datetime.now() <= start_time:
                time.sleep(1)
            config.session_start_time = date2s(start_time)
            config.session_end_time = date2s(end_time)
            ApiUtil.background_task_flow(flow,
                                         config,
                                         request.app.state.base_config,
                                         request.app.state.redisUtil,
                                         request.app.state.geoUtil,
                                         request.app.state.esdb)
            self.scheduled_threads_info['scheduled_repeat'] = int(self.scheduled_threads_info['scheduled_repeat']) + 1
            start_time = end_time + bean.scheduled_interval_minutes

    def append_queue(self, bean, request):
        flow = flowDao.get_flow_by_id(bean.flow_id)
        config = configDao.get_config_by_id(bean.config_id)
        if bean.is_scheduled:
            scheduled_thread = threading.Thread(target=self.scheduled_thread_method, args=(
                bean,
                flow,
                config,
                request
            ), daemon=True)
            self.scheduled_threads_info = {
                "is_scheduled": True,
                "config_id": bean.config_id,
                "flow_id": bean.flow_id,
                "description": bean.description,
                "thread": scheduled_thread,
                "name": scheduled_thread.name,
                "created_time": date2s(datetime.now()),
                "thread_id": scheduled_thread.ident,
                "isRunning": False,
                "isFinish": False,
                "start_time": "",
                "end_time": "",
                "scheduled_block_running": False,
                "scheduled_repeat": 0,
            }
        else:
            common_thread = threading.Thread(target=ApiUtil.background_task_flow, args=(
                flow,
                config,
                request.app.state.base_config,
                request.app.state.redisUtil,
                request.app.state.geoUtil,
                request.app.state.esdb
            ), daemon=True)
            self.task_queue.put(common_thread)
            self.threads_info.append({
                "is_scheduled": False,
                "config_id": bean.config_id,
                "flow_id": bean.flow_id,
                "description": bean.description,
                "thread": common_thread,
                "name": common_thread.name,
                "created_time": date2s(datetime.now()),
                "thread_id": common_thread.ident,
                "isRunning": False,
                "isFinish": False,
                "start_time": "",
                "end_time": "",
            })

    def get_task_list(self):
        status_list = [self.scheduled_threads_info]
        for info in self.threads_info:
            status_list.append({
                "flow_id": info["flow_id"],
                "config_id": info["config_id"],
                "description": info["description"],
                "name": info["name"],
                "created_time": info["created_time"],
                "is_alive": info["thread"].is_alive(),
                "isRunning": info["isRunning"],
                "isFinish": info["isFinish"],
                "start_time": info["start_time"],
                "end_time": info["end_time"]
            })
        return status_list

    def remove_finished_task(self):
        self.threads_info = [item for item in self.threads_info if not item['isFinish']]

    def stop_queue(self):
        self.stop_event.set()
        self.manager_thread.join()
